package com.gvtv.main.schedul;

import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;

import com.gvtv.main.execute.ExecuteJob;
import com.gvtv.main.job.JobInfo;
import com.gvtv.main.job.ParamInfo;
import com.gvtv.main.params.ParamsFactory;
import com.gvtv.main.util.AppTools;

public class SchedulEnv {

	private String id;
	private Map<String, String> env;
	
	public SchedulEnv(String id){
		this.id = id;
		env = Collections.synchronizedMap(new HashMap<String, String>());
	}
	public void add(String key, String value){
		if(env.containsKey(key)){
			env.remove(key);
		}
		env.put(key, value);
	}
	
	public void add(Map<String, String> env){
		if(env!=null&&!env.isEmpty()){
			Iterator<Entry<String, String>> iterator = env.entrySet().iterator();
			while (iterator.hasNext()) {
				Map.Entry<String, String> entry = (Entry<String, String>) iterator.next();
				this.add(entry.getKey(), this.getParamValue(entry.getValue()));
			}
		}
	}
	
	public String get(String key){
		return env.get(key);
	}
	
	public void remove(String key){
		if(env.containsKey(key)){
			env.remove(key);
		}
	}
	
	public void clear(){
		env.clear();
	}
	public String getParamValue(String str){
		if(StringUtils.isBlank(str)){
			return str;
		}
		Matcher ma = AppTools.pa.matcher(str);
		StringBuffer buf = new StringBuffer();
		while (ma.find()) {
			MatchResult mr = ma.toMatchResult();
			String key = mr.group(1);
			String value = this.get(key);
			if(value != null){
				ma.appendReplacement(buf,value);
			}else {
				ma.appendReplacement(buf,ParamsFactory.getInstance().toValue(key));
			}
		}
		ma.appendTail(buf);
		return buf.toString();
	}
	public Object getParamValue(Object Obj){
		if(Obj==null){
			return null;
		}
		return getParamValue((String)Obj);
	}
	
	public void convert(ExecuteJob executeJob){
		executeJob.setJobInfo(this.convert(executeJob.getJobInfo()));
	}
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public JobInfo convert(JobInfo jobInfo){
		JobInfo newJobInfo = new JobInfo();
		try {
			Map map = BeanUtils.describe(jobInfo);
			Iterator iterator = map.entrySet().iterator();
			while (iterator.hasNext()) {
				Map.Entry<String, Object> entry = (Entry<String, Object>) iterator.next();
				if("class".equals(entry.getKey())){
					continue;
				}
				if("params".equals(entry.getKey())){
					List<ParamInfo> list = jobInfo.getParams();
					for (ParamInfo paramInfo : list) {
						newJobInfo.addParam(this.convert(jobInfo, paramInfo));
					}
					continue;
				}
				//BeanUtils.setProperty(newJobInfo, entry.getKey(), this.getParamValue(entry.getValue()));
				BeanUtils.setProperty(newJobInfo, entry.getKey(), entry.getValue());
			}
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		}
		return newJobInfo;
	}
	
	@SuppressWarnings("unchecked")
	public ParamInfo convert(JobInfo jobInfo, ParamInfo paramInfo){
		ParamInfo newParamInfo = new ParamInfo();
		try {
			Map<String, Object> map = BeanUtils.describe(paramInfo);
			Iterator<Entry<String, Object>> iterator = map.entrySet().iterator();
			while (iterator.hasNext()) {
				Map.Entry<String, Object> entry = (Entry<String, Object>) iterator.next();
				if("class".equals(entry.getKey())){
					continue;
				}
				if("value".equals(entry.getKey())){
					BeanUtils.setProperty(newParamInfo, entry.getKey(), this.getParamValue(entry.getValue()));
				}else {
					BeanUtils.setProperty(newParamInfo, entry.getKey(), entry.getValue());
				}
				if(StringUtils.isNotBlank(newParamInfo.getName())){
					this.add("job."+jobInfo.getId()+"."+newParamInfo.getName(), newParamInfo.getValue());
				}
			}
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		}
		return newParamInfo;
	}
	
	@Override
	public String toString() {
		Iterator<Entry<String, String>> iterator = env.entrySet().iterator();
		StringBuilder sb = new StringBuilder();
		while (iterator.hasNext()) {
			Map.Entry<String, String> entry = (Entry<String, String>) iterator.next();
			sb.append(entry.getKey()).append("=").append(entry.getValue()).append(",");
		}
		sb.insert(0, "SchedulEnv [id="+id+",env=[").append("]");
		return sb.toString();
	}
	
	/*public static void main(String[] args) throws Exception {
		SchedulJobXmlParaser paraser = new SchedulJobXmlParaser();
		paraser.addFile("jobs/website-job.xml");
		paraser.paraser();
		List<SchedulInfo> schedulList = paraser.getSchedulList();
		for (SchedulInfo schedulInfo : schedulList) {
			SchedulEnv env = new SchedulEnv(schedulInfo.getId());
			for(JobInfo jobInfo: schedulInfo.getJobs()){
				JobInfo runJobInfo = env.convert(jobInfo);
				System.out.println(runJobInfo);
				for(ParamInfo paramInfo : runJobInfo.getParams()){
					System.out.println(paramInfo);
				}
			}
			System.out.println(env);
		}
		//env.clear();
		System.out.println("----------");
		Thread.sleep(1000*5);
		
		schedulList = paraser.getSchedulList();
		for (SchedulInfo schedulInfo : schedulList) {
			SchedulEnv env = new SchedulEnv(schedulInfo.getId());
			for(JobInfo jobInfo: schedulInfo.getJobs()){
				JobInfo runJobInfo = env.convert(jobInfo);
				System.out.println(runJobInfo);
				for(ParamInfo paramInfo : runJobInfo.getParams()){
					System.out.println(paramInfo);
				}
			}
			System.out.println(env);
		}
	}*/

}
